package de.saarland.uni.lego3d.server.gui.components;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Cursor;
import java.awt.Font;
import java.awt.GraphicsConfiguration;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Robot;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.image.BufferedImage;

import javax.media.j3d.Canvas3D;
import javax.media.j3d.Transform3D;
import javax.media.j3d.TransformGroup;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JLayeredPane;
import javax.swing.JPanel;
import javax.vecmath.Vector3f;

import com.sun.j3d.utils.picking.PickCanvas;
import com.sun.j3d.utils.universe.SimpleUniverse;

import de.saarland.uni.lego3d.server.gui.MainGUI;
import de.saarland.uni.lego3d.server.gui.handler.BrickPanelMouseHandler;
import de.saarland.uni.lego3d.server.gui.handler.KinectActionCursor;

public class Java3DPanel extends JLayeredPane {
	private static final long serialVersionUID = 2L;
	
	MainGUI mGui;
	
	KinectActionCursor lt;
	KinectActionCursor ltTmp;
	KinectActionCursor ltSave;
	
	/****************************LAYOUT CONSTRAINTS*****************************/
	public static final int VIEWSIZE_MAIN_WIDTH = 650;
	public static final int VIEWSIZE_MAIN_HEIGHT = 500;
	public static final int VIEWSIZE_DESELECTED_WIDTH = 180;
	public static final int VIEWSIZE_DESELECTED_HEIGHT = 180;
	
	/****************************COMMON USED CONSTANTS*****************************/
	public static final int VIEWPOINT_FRONT = 0;
	public static final int VIEWPOINT_LEFT = 1;
	public static final int VIEWPOINT_RIGHT = 2;
	public static final int VIEWPOINT_BACK = 3;
	public static final int VIEWPOINT_TOP = 4;
	
	private JPanel menuPanel = new JPanel(new BorderLayout());
	
	JButton btnAddTmp = new JButton("ADD TEMP");
	JButton btnSave = new JButton("SAVE");
	
	/**
	 * Canvas to recognizes clicks
	 */
	private PickCanvas pickCanvas;
	
	private Canvas3D canvas;
	
	private MouseListener ml;
	
	private JLabel label;
	
	/**
	 * Indicates viewpoint of this Panel
	 */
	public int viewpoint = -1;
	
	public BufferedImage getImage() {
		Point p = new Point();
		p = canvas.getLocationOnScreen();
		Rectangle bounds = new Rectangle(p.x, p.y, canvas.getWidth(), canvas.getHeight());
		try{
			Robot robot = new Robot();
			return robot.createScreenCapture(bounds);
		}catch (Exception e){
			e.printStackTrace();
			return null;
		}
	}
	
	public void setDeselected() {
		canvas.removeMouseListener(ml);
	    canvas.setSize(VIEWSIZE_DESELECTED_WIDTH, VIEWSIZE_DESELECTED_HEIGHT);
		
	    //Remove all mouselisteners from the buttons, since they are not visible anymore
	    for (MouseListener m : btnAddTmp.getMouseListeners()) {
	    	btnAddTmp.removeMouseListener(m);
	    }
	    
	    ml = null;
	    ml = new MouseListener() {
			@Override
			public void mouseReleased(MouseEvent e) {
			}
			
			@Override
			public void mousePressed(MouseEvent e) {
			}
			
			@Override
			public void mouseExited(MouseEvent e) {
				if (lt != null) {
					lt.interrupt();
				}
			}
			
			@Override
			public void mouseEntered(MouseEvent e) {
				lt = new KinectActionCursor(Java3DPanel.this, mGui, 1);
				lt.start();
			}
			
			@Override
			public void mouseClicked(MouseEvent e) {
			}
		};
		canvas.addMouseListener(ml);
		
		label.setFont(new Font("Arial", Font.BOLD, 14));
		menuPanel.setBackground(Color.BLACK);
		menuPanel.remove(btnAddTmp);
		menuPanel.remove(btnSave);
	}
	
	public void setCurrent() {
		if (lt != null) {
			lt.interrupt();
			try {
				lt.join();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		setCursor(Cursor.getDefaultCursor());
		canvas.setSize(VIEWSIZE_MAIN_WIDTH, VIEWSIZE_MAIN_HEIGHT);
		
		canvas.removeMouseListener(ml);
		
		ml = null;
		ml = new BrickPanelMouseHandler(viewpoint, pickCanvas);
		
		canvas.addMouseListener(ml);
		
		btnAddTmp.addMouseListener(new MouseListener() {
			@Override
			public void mouseReleased(MouseEvent e) {
			}
			
			@Override
			public void mousePressed(MouseEvent e) {
			}
			
			@Override
			public void mouseExited(MouseEvent e) {
				if (ltTmp != null) {
					ltTmp.interrupt();
				}
				setCursor(Cursor.getDefaultCursor());
			}
			
			@Override
			public void mouseEntered(MouseEvent e) {
				ltTmp = new KinectActionCursor(Java3DPanel.this, mGui, 2);
				ltTmp.start();
			}
			
			@Override
			public void mouseClicked(MouseEvent e) {
			}
		});
		
		btnSave.addMouseListener(new MouseListener() {
			@Override
			public void mouseReleased(MouseEvent e) {
			}
			
			@Override
			public void mousePressed(MouseEvent e) {
			}
			
			@Override
			public void mouseExited(MouseEvent e) {
				if (ltSave != null) {
					ltSave.interrupt();
				}
				setCursor(Cursor.getDefaultCursor());
			}
			
			@Override
			public void mouseEntered(MouseEvent e) {
				ltSave = new KinectActionCursor(Java3DPanel.this, mGui, 3);
				ltSave.start();
			}
			
			@Override
			public void mouseClicked(MouseEvent e) {
			}
		});
		
		label.setFont(new Font("Arial", Font.BOLD, 24));
		menuPanel.setBackground(Color.BLACK);
		menuPanel.add(btnAddTmp, BorderLayout.EAST);
		menuPanel.add(btnSave, BorderLayout.WEST);
	}
	
	public Java3DPanel (int _viewpoint, MainGUI mGui) {
		this.mGui = mGui;
		viewpoint = _viewpoint;
		
		//Confire UNIVERSE
		GraphicsConfiguration config = SimpleUniverse.getPreferredConfiguration();
		canvas = new Canvas3D(config);
	    
	    if (viewpoint == VIEWPOINT_FRONT) 
	    	canvas.setSize(VIEWSIZE_MAIN_WIDTH, VIEWSIZE_MAIN_HEIGHT);
	    else
	    	canvas.setSize(VIEWSIZE_DESELECTED_WIDTH, VIEWSIZE_DESELECTED_HEIGHT);
	    	
		//Set canvas to this panel
	    this.setLayout(new BorderLayout());
	    
		this.add(canvas, BorderLayout.SOUTH, 1);
		mGui.universe.addCanvas3D(canvas);
		
		//Set Label for this view
		label = new JLabel("", JLabel.CENTER);
		label.setForeground(Color.WHITE);
		
		switch (viewpoint) {
			case VIEWPOINT_FRONT:
				label.setText("Front view");
				break;
			case VIEWPOINT_LEFT:
				label.setText("Left view");
				break;
			case VIEWPOINT_RIGHT:
				label.setText("Right view");
				break;
			case VIEWPOINT_BACK:
				label.setText("Back view");
				break;
			case VIEWPOINT_TOP:
				label.setText("Top view");
				break;
		}
		menuPanel.add(label, BorderLayout.CENTER);
		this.add(menuPanel, BorderLayout.CENTER);

		
		// Set camera position
		Vector3f translateP = new Vector3f();
		Transform3D T3DS = new Transform3D();
		Transform3D T3DS2 = new Transform3D();
		TransformGroup tgVaizS = null;
		tgVaizS = mGui.universe.getViewingPlatform(viewpoint).getViewPlatformTransform();
		
		switch (viewpoint) {
			case VIEWPOINT_FRONT:
				translateP.set(0.0f, 5f, 5.0f);
				T3DS.rotX(Math.toRadians(-40));	
				break;

			case VIEWPOINT_BACK:
				translateP.set(0.0f, 5f, -8.0f);
				T3DS.rotX(Math.toRadians(40));
			    T3DS2.rotY(Math.toRadians(180));
			    T3DS.mul(T3DS2);
				break;

			case VIEWPOINT_LEFT:
				translateP.set(-6.5f, 5f, -1.5f);
				T3DS.rotZ(Math.toRadians(-40));
			    T3DS2.rotY(Math.toRadians(-90));
			    T3DS.mul(T3DS2);
				break;
				
			case VIEWPOINT_RIGHT:
				translateP.set(6.5f, 5f, -1.5f);
				T3DS.rotZ(Math.toRadians(40));
			    T3DS2.rotY(Math.toRadians(90));
			    T3DS.mul(T3DS2);
				break;
				
			case VIEWPOINT_TOP:
				translateP.set(0.0f, 10f, -1.5f);
				T3DS.rotX(Math.toRadians(-90));
				break;
				
			default:
				break;
		}
		
		T3DS.setTranslation(translateP);
		tgVaizS.setTransform(T3DS);
		
		pickCanvas = new PickCanvas(canvas, mGui.rootBranchGroup);
		pickCanvas.setMode(PickCanvas.BOUNDS);
		ml = new BrickPanelMouseHandler(viewpoint,pickCanvas);
	}
}
